package com.lx.aspect;

import com.lx.annotation.DataSource;
import com.lx.common.ContextConst;
import com.lx.datasource.DataSourceContextHolder;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 注解拦截器定义动态切换数据源
 *
 * @author 段誉
 * @create 2019-04-12 16:08
 */
@Component
@Aspect
public class DynamicDataSourceAspect {

  /**
   * 开始执行方法之前先设置数据源
   */
  @Before("execution(* com.lx.service..*.*(..))")
  public void before(JoinPoint point) {
    try {
      //判断类上的注解
      DataSource annotationOfClass = point.getTarget().getClass().getAnnotation(DataSource.class);

      //判断方法上是否存在注解
      String methodName = point.getSignature().getName();
      Class[] parameterTypes = ((MethodSignature) point.getSignature()).getParameterTypes();
      Method method = point.getTarget().getClass().getMethod(methodName, parameterTypes);
      DataSource methodAnnotation = method.getAnnotation(DataSource.class);
      methodAnnotation = methodAnnotation == null ? annotationOfClass : methodAnnotation;

      ContextConst.DataSourceType dataSourceType =
              methodAnnotation != null && methodAnnotation.value() != null
                      ? methodAnnotation.value() : ContextConst.DataSourceType.PRIMARY;

      //设置数据源
      DataSourceContextHolder.setDataSource(dataSourceType.name());
    } catch (NoSuchMethodException e) {
      e.printStackTrace();
    }
  }

  /**
   * 方法执行完毕清除设置的数据源
   */
  @After("execution(* com.lx.service..*.*(..))")
  public void after(JoinPoint point) {
    DataSourceContextHolder.clearDataSource();
  }
}
